package example.demo.component.collect;


import example.demo.QuartzSimpleUseApp;
import example.demo.scope.CostumerScopeRegister;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.web.servlet.context.ServletWebServerInitializedEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.MethodMetadata;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;

/*
 * collect-controller-collectTag方法的url
 * @RequestMapping("/api/system/print-date") 配置一个，且都要带上 /
 * @RequestMapping(path = "/date")
 *
 * 借助事件回调机制
 */
@Component
public class CollectTagByEvent implements ApplicationListener<ServletWebServerInitializedEvent>/* , ApplicationContextAware*/ {

    @Override
    public void onApplicationEvent(ServletWebServerInitializedEvent event) {
        List<String> urls = new ArrayList<>(4);
        final ConfigurableListableBeanFactory beanFactory = CostumerScopeRegister.configurableListableBeanFactory;
        String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
//        Arrays.stream(beanDefinitionNames).map(name -> String.format("bean-name == [ %s ]", name)).forEach(System.out::println);
        for (String beanName : beanDefinitionNames) {
            //ApplicationContext 无getBeanDefinition(BeanName)
            BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
            //我的controller肯定是scan的，所以先满足ScannedGenericBeanDefinition这个
            if (beanDefinition instanceof ScannedGenericBeanDefinition) {
                ScannedGenericBeanDefinition scanBean = (ScannedGenericBeanDefinition) beanDefinition;
                AnnotationMetadata metadata = scanBean.getMetadata();
                //再看这个类是否有RestController or Controller
                if (metadata.hasAnnotation(RestController.class.getName()) || metadata.hasAnnotation(Controller.class.getName())) {
                    //拿到所有标记方法信息
                    Set<MethodMetadata> collectTagMethods = metadata.getAnnotatedMethods(CollectTag.class.getName());
                    //拿到类上面的url
                    if (metadata.hasAnnotation(RequestMapping.class.getName())) {
                        Map<String, Object> attributes = metadata.getAnnotationAttributes(RequestMapping.class.getName());
                        String[] classUrlPath = (String[]) attributes.get("value");
                        //再去拿方法上的url
                        for (MethodMetadata tagMethod : collectTagMethods) {
                            Map<String, Object> requestAnno = tagMethod.getAnnotationAttributes(RequestMapping.class.getName());
                            String[] methodUrlPath = (String[]) (requestAnno.get("value") == null ? requestAnno.get("path") : requestAnno.get("value"));
                            if (null != classUrlPath) {
                                //url拼接
                                urls.add(classUrlPath[0] + methodUrlPath[0]);
                            }
                        }
                    }
                }
            }
        }
//        System.out.println(urls);
        try {
            QuartzSimpleUseApp.listExchanger.exchange(urls);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
